package ru.ipo.dces.plugins.admin.components;

import info.clearthought.layout.TableLayout;
import ru.ipo.dces.client.components.ContestChoosingPanel;
import ru.ipo.dces.clientservercommunication.ContestDescription;
import ru.ipo.dces.plugins.admin.resources.ImageResources;

import javax.swing.*;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.html.HTMLDocument;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import static ru.ipo.dces.plugins.admin.resources.ImageResources.buttonSelfRegistrationResource;

public class ContestInformationPanel extends JPanel {

    private JTextPane informationPane;
    private ContestDescription desc;
    private static final DateFormat CONTEST_DATE_FORMATTER = DateFormat.getDateInstance(DateFormat.LONG);
    private static final DateFormat CONTEST_TIME_FORMATTER = new SimpleDateFormat("hh:mm");
    private static final DateFormat df = DateFormat.getTimeInstance(DateFormat.LONG);
    private Timer tickPerSecond;
    private static final boolean DEBUG_ALWAYS_TICK_PER_SECOND = false;

    public ContestInformationPanel() {
        int separatorGap = 5;
        setLayout(new TableLayout(new double[] {TableLayout.FILL}, new double[] {separatorGap, TableLayout.FILL}));
        informationPane = new JTextPane();
        informationPane.setEditable(false);
        informationPane.setDisabledTextColor(Color.BLACK);
        informationPane.setFocusable(false);
        informationPane.setContentType("text/html");
        informationPane.setBorder(null);
        informationPane.setBackground(getBackground());
        add(informationPane, "0, 1");
    }

    public void clear() {
        informationPane.setText("");
    }

    public void setContest(ContestDescription contestDescription) {
        desc = contestDescription;
        initView();
        runTimer();
        update();
    }

    private void initView() {
        StringBuilder content = new StringBuilder();
        Date now = new Date();

        content.append("<html>");
        content.append("<head><style type='text/css'>" +
                //"p {font-family: Times new Roman;}" +
                "</style></head>");
        content.append("<body bgcolor='").append(colorToHtml(getBackground())).append("'>");

        String titleFontColor = "black";
        if (getContestStatus() != null)
            switch (getContestStatus()) {
                case -1:
                    titleFontColor = colorToHtml(IconListRenderer.CONTEST_FINISHED);
                    break;
                case 0:
                    titleFontColor = colorToHtml(IconListRenderer.CONTEST_IS_NOW);
                    break;
                case 1:
                    titleFontColor = colorToHtml(IconListRenderer.CONTEST_HAS_NOT_BEGAN);
            }
        content.append(desc.name).append("<br>");
        if (desc.registrationType == ContestDescription.RegistrationType.Self) {
            content.append("<img src=").append(buttonSelfRegistrationResource).append(">");
            content.append("&nbsp;<font color='").append(titleFontColor).append("'>Соревнование с саморегистрацией</font><br><br>");
        }
        if (desc.registrationType == ContestDescription.RegistrationType.ByAdmins) {
            content.append("<img src=").append(ImageResources.buttonAdminRegistrationResource).append(">");
            content.append("&nbsp;<font color='").append(titleFontColor).append("'>Соревнование без саморегистрации</font><br><br>");
        }

//        content.append("id соревнования = ").append(desc.contestID).append("<br>");
//        content.append("Текущее время ").append("<span id='cur_time'>").append(df.format(new Date())).append("</span><br>");

        Integer contestStatus = getContestStatus();
        if (contestStatus != null) {
            String statusDescription = null;
            switch (contestStatus) {
                case -1:
                    statusDescription = "<p>Соревнование окончено <span id='desc_time'> " +
                            getRightTimeRepresentation(now.getTime() - desc.finish.getTime()) + "</span> назад</p>";
                    break;
                case 0:
                    statusDescription = "Соревнование идёт сейчас закончится через <span id='desc_time'>" +
                            getRightTimeRepresentation(desc.finish.getTime() - now.getTime()) + "</span>";
                    break;
                case 1:
                    statusDescription = "Соревнование начнётся через <span id='desc_time'>" +
                            getRightTimeRepresentation(desc.start.getTime() - now.getTime()) + "</span>";
            }

            content.append(statusDescription).append("<br>");
            content.append("<table>");
            content.append("<tr><td><b>Начало: </b></td><td>").
                    append(contestTimeFormat(desc.start)).append("</td></tr>");
            content.append("<tr><td><b>Окончание: </b></td><td>").
                    append(contestTimeFormat(desc.finish)).append("<br></td><tr>");
            content.append("</table>");
        }
        content.append("</html>");
        informationPane.setText(content.toString());
    }

    private String contestTimeFormat(Date time) {
        return CONTEST_DATE_FORMATTER.format(time) + " " + CONTEST_TIME_FORMATTER.format(time);
    }

    private void runTimer() {
        ActionListener actionListener = new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                update();
            }
        };

        tickPerSecond = new Timer(1000, actionListener);
        Timer tickPerMinute = new Timer(1000 * 60, actionListener);

        tickPerMinute.start();
    }

    private void update() {
        if (desc == null) {
            return;
        }
        Integer contestStatus = getContestStatus();
        if (contestStatus == null) {
            return;
        }

        HTMLDocument document = (HTMLDocument) informationPane.getDocument();
        String descTime = "desc_time";

        long time = -1;
        switch (contestStatus) {
            case -1:
                time = new Date().getTime() - desc.finish.getTime();
                setElementContents(document, descTime, getRightTimeRepresentation(time));
                break;
            case 0:
                time = desc.finish.getTime() - new Date().getTime();
                setElementContents(document, descTime, getRightTimeRepresentation(time));
                break;
            case 1:
                time = desc.start.getTime() - new Date().getTime();
                setElementContents(document, descTime, getRightTimeRepresentation(time));
        }

        //noinspection ConstantConditions
        if ((time != -1 && time <= 1000 * 60 * 2) || DEBUG_ALWAYS_TICK_PER_SECOND) {
            if (!tickPerSecond.isRunning())
                tickPerSecond.start();
        } else {
            if (tickPerSecond.isRunning())
                tickPerSecond.stop();
        }

        setElementContents(document, "cur_time", df.format(new Date()));
    }

    private void setElementContents(Document d, String elementID, String text) {
        try {
            HTMLDocument htmlDocument = (HTMLDocument) d;
            Element e = htmlDocument.getElement(elementID);
            if (e == null)
                return;
            htmlDocument.setOuterHTML(e, "<span id='" + elementID + "'>" + text + "</span>");
        } catch (Exception ignored) {
        }
    }

    private Integer getContestStatus() {
        if (desc.start == null || desc.finish == null)
            return null;

        Date currentTime = new Date();
        if (currentTime.compareTo(desc.finish) > 0)
            return -1;
        else if (currentTime.compareTo(desc.start) < 0)
            return 1;
        else
            return 0;
    }

    private String getRightTimeRepresentation(long time) {
        time /= 1000;

        int sec = (int) (time % 60);
        time /= 60;
        if (time == 0)
            return sec + " сек.";

        int min = (int) (time / 60);
        time /= 60;
        if (time == 0)
            return min + " мин. " + sec + " сек.";

        int hours = (int) (time % 24);
        time /= 24;
        if (time == 0)
            return hours + " ч. " + min + " мин.";

        return time + " дн. " + hours + " ч.";
    }

    private String prependZeros(String s, int neededLength) {
        while (s.length() < neededLength)
            s = "0" + s;
        return s;
    }

    private String colorToHtml(Color color) {
        return "#" +
                prependZeros(Integer.toHexString(color.getRed()), 2) +
                prependZeros(Integer.toHexString(color.getGreen()), 2) +
                prependZeros(Integer.toHexString(color.getBlue()), 2);
    }
}
